import {
  ColumnDef,
  ColumnFiltersState,
  flexRender,
  getCoreRowModel,
  getExpandedRowModel,
  getFacetedRowModel,
  getFacetedUniqueValues,
  getFilteredRowModel,
  getPaginationRowModel,
  getSortedRowModel,
  SortingState,
  useReactTable,
  VisibilityState,
  Row
} from '@tanstack/react-table'
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow
} from '@renderer/components/ui/table'
import { DataTablePagination } from '@renderer/components/table/data-table-pagination'
import { DataTableToolbar } from './data-table-toolbar'
import { DataTableItem } from './data-table-item'
import { Fragment, useState } from 'react'

interface HasMark {
  readonly mark: string
}

interface DataTableProps<TData extends HasMark, TItemData extends HasMark> {
  data: TData[]
  items: TItemData[]
  useColumns: () => ColumnDef<TData>[]
  useItemColumns: (sup: TData) => ColumnDef<TItemData>[]
  renderSubComponent: (row: Row<TData>, items: TItemData[]) => TItemData[]
  getRowCanExpand: (row: Row<TData>) => boolean
}

export function DataTable<TData extends HasMark, TItemData extends HasMark>({
  data,
  items,
  useColumns,
  useItemColumns,
  renderSubComponent,
  getRowCanExpand
}: DataTableProps<TData, TItemData>) {
  const [rowSelection, setRowSelection] = useState({})
  const [columnVisibility, setColumnVisibility] = useState<VisibilityState>({})
  const [columnFilters, setColumnFilters] = useState<ColumnFiltersState>([])
  const [sorting, setSorting] = useState<SortingState>([])

  const columns = useColumns()

  const table = useReactTable({
    data,
    columns,
    state: {
      sorting,
      columnVisibility,
      rowSelection,
      columnFilters
    },
    initialState: {
      pagination: {
        pageSize: 10
      }
    },
    enableRowSelection: true,
    onRowSelectionChange: setRowSelection,
    onSortingChange: setSorting,
    onColumnFiltersChange: setColumnFilters,
    onColumnVisibilityChange: setColumnVisibility,
    getCoreRowModel: getCoreRowModel(),
    getFilteredRowModel: getFilteredRowModel(),
    getPaginationRowModel: getPaginationRowModel(),
    getSortedRowModel: getSortedRowModel(),
    getFacetedRowModel: getFacetedRowModel(),
    getFacetedUniqueValues: getFacetedUniqueValues(),
    getExpandedRowModel: getExpandedRowModel(),
    getRowCanExpand
  })

  return (
    <div className="flex flex-col gap-4">
      <DataTableToolbar table={table} />
      <div className="overflow-hidden rounded-md border">
        <Table>
          <TableHeader>
            {table.getHeaderGroups().map((headerGroup) => (
              <TableRow key={headerGroup.id}>
                {headerGroup.headers.map((header) => {
                  return (
                    <TableHead key={header.id} style={{ width: header.getSize() }}>
                      {header.isPlaceholder
                        ? null
                        : flexRender(header.column.columnDef.header, header.getContext())}
                    </TableHead>
                  )
                })}
              </TableRow>
            ))}
          </TableHeader>
          <TableBody>
            {table.getRowModel().rows?.length ? (
              table.getRowModel().rows.map((row) => (
                <Fragment key={row.id + row.original.mark}>
                  <TableRow
                    key={row.id + row.original.mark + '-base'}
                    data-state={row.getIsSelected() && 'selected'}
                  >
                    {row.getVisibleCells().map((cell) => (
                      <TableCell key={cell.id}>
                        {flexRender(cell.column.columnDef.cell, cell.getContext())}
                      </TableCell>
                    ))}
                  </TableRow>
                  {row.getIsExpanded() && (
                    <TableRow
                      key={row.original.mark + '-isExpanded'}
                      data-state={row.getIsSelected() && 'selected'}
                    >
                      {/* 设置占据整行 */}
                      <TableCell colSpan={columns.length} className="p-0 bg-muted">
                        {row.getVisibleCells().length > 0 &&
                          renderSubComponent(row, items).length > 0 && (
                            <DataTableItem
                              sup={row.original}
                              data={renderSubComponent(row, items)}
                              useColumns={useItemColumns}
                            />
                          )}
                      </TableCell>
                    </TableRow>
                  )}
                </Fragment>
              ))
            ) : (
              <TableRow>
                <TableCell colSpan={columns.length} className="h-24 text-center">
                  No results.
                </TableCell>
              </TableRow>
            )}
          </TableBody>
        </Table>
      </div>
      <DataTablePagination table={table} />
    </div>
  )
}
